<!DOCTYPE html>
<html lang="zh-cn">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">




<title>网站性能优化之图片优化 | Miles`s</title>

<link rel="stylesheet" href="https://mada.gitee.io/notes//css/styles.css">

<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.2.0/css/all.css" 
integrity="sha384-hWVjflwFxL6sNzntih27bfxkr27PmbbK/iSvJ+a4+0owXq79v+lsFkW54bOGbiDQ" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.3.1.js" integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60=" crossorigin="anonymous"></script>


<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/zenburn.min.css" crossorigin="anonymous" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js" integrity="sha256-/BfiIkHlHoVihZdc6TFuj7MmJ0TWcWsMXkeDFwhi0zw=" crossorigin="anonymous"></script>
<script>hljs.initHighlightingOnLoad();</script>
<script src="https://mada.gitee.io/notes//js/highlight.js"></script>






<div class="container">
    <nav class="navbar level">
      <div class="navbar-brand">
          <a class="nav-item" href="https://mada.gitee.io/notes/"><h1 class="title is-3">Miles`s</h1></a>
      </div>           
      <div class="navbar-menu has-text-centered is-active">
          <div class="navbar-end is-centered">
              
           </div>
      </div>
    </nav>
  </div>
<div class="container">
  <h2 class="subtitle is-6">November 16, 2016</h2>
  <h1 class="subtitle is-size-4-mobile is-size-3-desktop">网站性能优化之图片优化</h1>
  <div class="content">
    

<p>图像优化是最易实施的方案。通常，我们可以在只有轻微质量损耗和无损的前提下大幅减小图像的大小。</p>

<h1 id="背景">背景</h1>

<p><strong>图形</strong></p>

<p>网站的Logo、草图、图表、大部分动画和图标都属于图形。这些图像通常由连续的线条或其他尖锐的颜色过渡组成，颜色数量相对较少。</p>

<p><strong>照片</strong></p>

<p>通常由数百万级的颜色，并且包含平滑的颜色过渡和渐变</p>

<p><strong>像素和RGB</strong></p>

<p>图像由像素组成，是图像中最小的信息单元。RGB颜色模型是最常见的一种，采用（R），绿（G）和蓝（B）的数量多少的方式来描述一个像素。</p>

<p><strong>真彩色图像VS调色板图像格式</strong></p>

<p><strong>真彩色图像</strong>：<code>256*256*256</code>可以得到16777216种组成。可以支持这么多颜色的图像格式叫做真彩色图像格式；比如jpeg和真彩色类型png。</p>

<p><strong>调色板图像格式</strong>：为了存储图像信息时节省一些空间，有一项技术是将图像中各种颜色提取出来建立一个表，这个表通常叫做调色板（也可以成为索引）。有了这个颜色表，就可以通过将调色板中的条目和每个像素重新匹配，达到重新绘制整个图像的目的。</p>

<p>调色板可以包含任意RGB颜色值，但是最常用的调色板格式－－gif和png8，会限制最多256种。
你可以从1600+万种颜色中选择你需要的值，但是这个图像中最多只能有256种颜色。</p>

<p><strong>透明和alpha通道（RGBA）</strong>
在RGB的基础上做了扩张。额外的成分A表示透明，0～255值，实际上不同的程序会定义为0%～100%，或者0～127.</p>

<p><strong>隔行扫描</strong></p>

<p>当网速很慢时，大图像会随着下载的进度逐行显示，从上到下每次显示一行，缓慢地向下递进。为了提高用户体验，部分图像进行<strong>隔行扫描</strong>.让用户在完整的下载图像之前，看到图像的一个粗略的版本。</p>

<h1 id="压缩方式">压缩方式</h1>

<ol>
<li>无损压缩，在不损耗质量的前提下，将文件的大小减到最小。就算精确到像素级别，优化后的图像和原图在视觉质量上也是一样的。这样方法是：移除元数据，对颜色或像素信息进行更好的压缩，以及删除对Web显示没有必要的块信息（针对png的情况）。</li>
<li>有损压缩，优化之前，需要确定图像的颜色数，分辨率和清晰度。对这几个参数进行<strong>有损优化</strong>，同时也会影响整个图像的质量。图像也许可能拥有更少的颜色，对于jpeg格式图像来说，可能意味着减少图像的编码。对于jpeg图像来说，虽然60%～70%的质量是公认的标准，但确实有些图像或背景需要更高或更低的质量。如何选择，需要根据设计师的创意决定。当然，也可以根据使用空间进行区域压缩，比如：人像部分使用80%的压缩，背景部分使用30％的质量。</li>
</ol>

<h1 id="图片格式">图片格式</h1>

<p><strong>gif</strong></p>

<p>一种调色板图像，允许一个二进制类型的透明度。每个像素要么透明，要么完全不透明，支持动画，无损，也就是说你可以打开任意一个gif文件，做一些修改，保存关闭不会损失任何质量。支持歌行扫描</p>

<p>适合显示图形，png8是用来显示图形的最佳格式。所以需要使用动画时才应该是用gif。</p>

<p><strong>jpeg</strong></p>

<p>是照片存储的实际标准。考虑到人类眼睛对颜色和光线强弱的感知，这种格式通过各种技术来减少所需要的信息，所以它能经过高度压缩的文件存储高分辨率的图像。</p>

<p>有损：用户可以设置自定义的质量级别。质量从0-100，但是就算设置为100，同样会有一定的治疗损耗。</p>

<p>Notes：当对某个图像进行多项编辑操作时，最好使用无损的图像格式来保存中间结果。</p>

<p>也有少数操作是无损的：
* 旋转（90度，180度和270度的情况下）
* 裁剪
* 翻转（水平或者垂直）
* 从标准模式切换到渐进模式，反之亦然
* 编辑图像元数据</p>

<p>不支持透明或动画
Progressive JPEG支持隔行扫描</p>

<p><a href="http://www.uisdc.com/picture-optimization-techniques">更详细的jpg原理介绍</a></p>

<p><strong>png</strong></p>

<ul>
<li>真色彩和调色板png格式：大致分为两种。</li>
<li>透明：</li>
<li>动画：暂不支持</li>
<li>无损</li>
<li>逐行扫描</li>
<li>隔行扫描</li>
</ul>

<p><strong>WebP</strong></p>

<p>WebP（发音 weppy，<a href="https://developers.google.com/speed/webp/">项目主页</a>），是一种支持有损压缩和无损压缩的图片文件格式，派生自图像编码格式 VP8。根据 Google 的测试，无损压缩后的 WebP 比 PNG 文件少了 45％ 的文件大小，即使这些 PNG 文件经过其他压缩工具压缩之后，WebP 还是可以减少 28％ 的文件大小。</p>

<p>png原图，png无损，webp无损，png有损，webp有损对比测试结果：</p>

<p><img src="../../images/performance/webp-test.png" alt="webp" /></p>

<ul>
<li>PNG 转 WebP 的压缩率要高于 PNG 原图压缩率，同样支持有损与无损压缩</li>
<li>转换后的 WebP 体积大幅减少，图片质量也得到保障（同时肉眼几乎无法看出差异）</li>
<li>转换后的 WebP 支持 Alpha 透明和 24-bit 颜色数，不存在 PNG8 色彩不够丰富和在浏览器中可能会出现毛边的问题</li>
</ul>

<p>JPEG 转 WebP 的效果更佳.</p>

<p>浏览器支持情况：</p>

<p><img src="../../images/performance/webp-support.jpg" alt="support" /></p>

<p>可以使用<a href="http://scottjehl.github.io/picturefill/">picturefill</a>解决浏览器支持性问题。</p>

<p>WebP 编码主要有几个参数：</p>

<p><strong>lossless</strong>: YES:有损编码 NO:无损编码。WebP 主要优势在于有损编码，其无损编码的性能和压缩比表现一般。</p>

<p><strong>quality</strong>: [0~100] 图像质量，0表示最差质量，文件体积最小，细节损失严重，100表示最高图像质量，文件体积较大。该参数只针对有损压缩有明显效果。Google 官方的建议是 75，腾讯在对 WebP 评测时给出的建议也是 75。在这个值附近，WebP 能在压缩比、图像质量上取得较好的平衡。</p>

<p><strong>method</strong>: [0~6] 压缩比，0表示快速压缩，耗时短，压缩质量一般，6表示极限压缩，耗时长，压缩质量好。该参数也只针对有损压缩有明显效果。调节该参数最高能带来 20% ～ 40% 的更高压缩比，但相应的编码时间会增加 5～20 倍。Google 推荐的值是 4。</p>

<p>对于编码无损图片来说，quality=0, method=0~3 是相对来说比较合适的参数，能够节省编码时间，同时也有不错的压缩比。无损编码图片，quality=75, method=2~4 是比较合适的参数，能在编码时间、图片质量、文件体积之间有着不错的平衡。</p>

<p>具体的webp信息可见：</p>

<p><a href="https://isux.tencent.com/introduction-of-webp.html">WebP 探寻之路</a>
<a href="http://blog.ibireme.com/2015/11/02/mobile_image_benchmark/">移动端图片格式调研</a></p>

<p><strong>APNG</strong></p>

<p>APNG 目前并没有被 PNG 官方所接受，所以 libpng 并不能直接解码 APNG。但由于 APNG 只是基于 PNG 的一个简单扩展，所以在已经支持 PNG 的平台上，可以很轻松的用少量代码实现 APNG 的编解码。另外，在支持 canvas 的浏览器上，可以用 apng-canvas 直接显示 APNG 动画。APNG 压缩最好的工具目前是 <a href="http://sourceforge.net/projects/apngasm/">apngasm</a>，大部分图形化工具比如腾讯的 <a href="http://isparta.github.io/index.html">iSparta</a> 都是基于这个工具开发的。</p>

<p>就目前而言， APNG 是 GIF 最好的替代了：实现简单，可用范围广，压缩比不错，显示效果好。</p>

<p><strong>svg</strong></p>

<p>是一种矢量图片，支持透明，缩放，动画，除了android 2.3的手机，其它场景都支持，是一种比较好的图片代替方案。 优势：</p>

<ul>
<li>矢量图形，不受像素影响——SVG的这个特性使得它在不同的平台或者媒体下表现良好，无论屏幕分辨率如何</li>
<li>SVG对动画的支持较好；其DOM结构可以被其特定语法或者Javascript控制，从而轻松的实现动画</li>
<li>Javascript可以完全控制SVG Dom 元素</li>
<li>SVG的结构是 XML，其可访问性（盲文、声音朗读等）、可操作性、可编程性、可被CSS样式化完胜Canvas。另外，其支持 ARIA 属性，使其如虎添翼。</li>
</ul>

<p>劣势：</p>

<ul>
<li>DOM比正常的图形慢，而且如果其结点多而杂，就更慢了</li>
<li>不适合网页游戏等；当然，我们可以结合 Canvas + SVG来实现</li>
</ul>

<p>另外，bpg,JPEG-2000,JPEG-XR,mozjpg,sharpP等，使用频率不大，且很多浏览器没有好的支持，或是没有很好的压缩，解码工具，暂不做介绍。</p>

<h1 id="图片格式的选择">图片格式的选择</h1>

<p>如果效果真的需要图片来表现，那么选择图片格式是优化的第一步。我们经常听到的词语包括矢量图、标量图、SVG、有损压缩、无损压缩等等，我们首先说明各种图片格式的特点：</p>

<p><img src="../../images/performance/img-select.png" alt="img-select" /></p>

<p><strong>颜色丰富的照片，JPG是通用的选择</strong></p>

<ul>
<li>人眼的结构很适合查看JPG压缩后的照片，可以充分的忽略并在脑中补齐细节</li>
<li>JPG在压缩率不高时保留的细节还是不错的</li>
<li>WebP能够比JPG减少30%的体积，但目前兼容性较差</li>
</ul>

<p><strong>如果需要较通用的动画，GIF是唯一可用的选择</strong></p>

<ul>
<li>GIF支持的颜色范围为256色，而且仅支持完全透明/完全不透明</li>
<li>GIF在显示颜色丰富的动画时可能出现颜色不全、边缘锯齿等问题</li>
</ul>

<p><strong>如果图片由标准的几何图形组成，或需要使用程序动态控制其显示特效，可以考虑SVG格式</strong></p>

<ul>
<li>SVG是使用XML定义的矢量图形，生成的图片在各种分辨率下均可自由放缩</li>
<li>SVG中可以通过JavaScript等接口自由变换图片特效，可以完成其中部分元素的自由旋转、移动、变换颜色等</li>
</ul>

<p><strong>如果需要清晰的显示颜色丰富的图片，PNG比较好</strong></p>

<ul>
<li>PNG-8能够显示256种颜色，但能够同时支持256阶透明，因此颜色数较少但需要半透明的情景（如微信动画大表情）可以考虑PNG-8</li>
<li>PNG-24可以显示真彩色，但不支持透明，颜色丰富的图片推荐使用（如屏幕截图、界面设计图）</li>
<li>PNG-32可以显示真彩色，同时支持256阶透明，效果最好但尺寸也最大</li>
</ul>

<h1 id="优化png格式的图像">优化png格式的图像</h1>

<p>png格式的图像信息保存在<strong>块</strong>中。这种方式有利于扩张。但是对于web显示来说，大部分的块都非必要，完美要安全的删除。</p>

<p>一些列的工具介绍：<a href="http://www.uisdc.com/photo-optimization-tools">一网打尽！优秀图像优化工具推荐</a></p>

<p><strong>gulp</strong>自动压缩：</p>

<p><strong>gulp-tinypng</strong> 使用<a href="https://tinypng.com/">tinypng</a></p>

<p><code>npm install --save-dev gulp-tinypng</code></p>

<pre><code class="language-js">var gulp = require('gulp');
var tinypng = require('gulp-tinypng');

gulp.task('tinypng', function () {
    gulp.src('src/**/*.png')
        .pipe(tinypng('API_KEY'))
        .pipe(gulp.dest('compressed_images'));
});
</code></pre>

<h1 id="剥离jpeg的元数据">剥离jpeg的元数据</h1>

<p>jpeg文件中包含如下的元数据：</p>

<ul>
<li>注释</li>
<li>应用程序定义的内部信息</li>
<li>EXIF信息，比如拍摄用的相机型号，拍摄日期，拍摄位置，缩略图等甚至还可以包含音频信息等。</li>
</ul>

<p>这些元数据不会影响图像显示，可以被安全地移除，对元数据的处理，也是进行无损压缩的方法之一，可以将文件中的那些不需要的部分直接剔除，而不会影响视觉质量。</p>

<p>工具推荐：<a href="http://www.uisdc.com/7-practical-compression-tool">图片压缩不求人！7款超实用的压缩神器推荐</a></p>

<h1 id="将gif专程png">将gif专程png</h1>

<p>png8支持gif所有的功能，所以将gif转成png8，视觉上感觉不会变化。之后再对png进一步优化。</p>

<p><strong>工具</strong>：imageMagick</p>

<h1 id="优化gif动画">优化gif动画</h1>

<p><strong>工具：</strong> gifsicle</p>

<h1 id="使用渐进jpeg格式来存储大图像">使用渐进jpeg格式来存储大图像</h1>

<p>在浏览器中逐步进行渲染，允许用户在图像还在传输时，就看到一个低分辨率的图像。
大于<strong>10kb</strong>的图像可以通过格式转换成渐进jpeg图像来获得更好的压缩率，较小的图像适合非渐进的标准jpeg图像。</p>

<p>可以使用photoshop“存储为web所用格式”，勾选“连续”选项生成。</p>

<p><img src="./jpeg-progressive.png" alt="jpeg progressive.png" /></p>

<h1 id="使用picture-source加载最优图片">使用picture，source加载最优图片。</h1>

<h2 id="使用最优图片格式">使用最优图片格式</h2>

<p>使用<a href="http://scottjehl.github.io/picturefill/">picturefill</a>更好的支持picture</p>

<p>在android设备默认浏览器，以及chrome等设备加载压缩率更好的webp格式的图片，而在不支持该格式的ie或者firefox等浏览器加载支持性更好的jpeg图像或者png图像。</p>

<pre><code class="language-html">&lt;picture&gt;
  &lt;source srcset=&quot;examples/images/large.webp&quot; type=&quot;image/webp&quot;&gt;
  &lt;img srcset=&quot;examples/images/large.jpg&quot; alt=&quot;…&quot;&gt;
&lt;/picture&gt;
</code></pre>

<p><strong>工具：</strong></p>

<p><strong>gulp</strong></p>

<p>gulp-webp
<code>npm install --save-dev gulp-webp</code></p>

<pre><code class="language-js">const gulp = require('gulp');
const webp = require('gulp-webp');

gulp.task('default', () =&gt;
    gulp.src('src/image.jpg')
        .pipe(webp())
        .pipe(gulp.dest('dist'))
);
</code></pre>

<p>智图
<code>npm install --save-dev gulp-imageisux</code></p>

<pre><code class="language-js">
var imageisux = require('gulp-imageisux');
gulp.task('imageisux', function() {
    return gulp.src(['img/*'])
               .pipe(imageisux('/dirpath/',true));
});

</code></pre>

<p>客户端：
<a href="http://zhitu.isux.us/">腾讯智图</a></p>

<h2 id="使用最优图片尺寸">使用最优图片尺寸</h2>

<pre><code class="language-html">
&lt;img
  sizes=&quot;(min-width: 40em) 80vw, 100vw&quot;
  srcset=&quot;examples/images/medium.jpg 375w,
          examples/images/large.jpg 480w,
          examples/images/extralarge.jpg 768w&quot;
  alt=&quot;…&quot;&gt;

</code></pre>

<p>具体的属性介绍参考：
<a href="https://bitsofco.de/the-srcset-and-sizes-attributes/">Responsive Images - The srcset and sizes Attributes</a></p>

<p><a href="http://ericportis.com/posts/2014/srcset-sizes/">Srcset and sizes</a></p>

<p><strong>工具：</strong> <a href="http://www.responsivebreakpoints.com/">Responsive Image Breakpoints Generator</a></p>

<h1 id="使用base64编码">使用base64编码</h1>

<h2 id="内联图片">内联图片</h2>

<p>通过使用<code>data:URL</code>模式在Web页面中包含图片但无需任何额外的HTTP请求。</p>

<p><code>data:[&lt;mediatype&gt;][;base64],&lt;data&gt;</code></p>

<p><code>Base64</code>编码会增加图片的大小，因此整体下载量会增加。</p>

<p>由于data:URL是内联在页面中，在跨越不同的页面时不会被缓存。<strong>不要去内联Logo</strong>，好的做法是实用CSS并将内联图片作为背景。将该CSS规则放在外部样式表中，意味着数据可以缓存在样式表内部。</p>

<pre><code>.logo{
	background-image:url();
}
</code></pre>

<h1 id="图片地图">图片地图</h1>

<p>map area</p>

<p>通过一张图片的不同位置做不同的链接跳转，以减少图片的多次请求。</p>

<pre><code class="language-html">    &lt;img usemap=&quot;#map1&quot; src=&quot;img.jpeg&quot;&gt;
    &lt;map name=&quot;map1&gt;
        &lt;area shape=&quot;rect&quot; coords=&quot;0,0,31,31&quot; href=&quot;a.html&quot; title=&quot;home&quot;&gt; 
        &lt;area shape=&quot;rect&quot; coords=&quot;40,0,31,31&quot; href=&quot;b.html&quot; title=&quot;gifts&quot;&gt; 
    &lt;/map&gt;

</code></pre>

<h1 id="高度优化的css-sprite">高度优化的CSS Sprite</h1>

<ul>
<li>按照颜色合并</li>
<li>避免不必要的空白</li>
<li>将元素水平排列，缩小Sprite</li>
<li>将颜色限制在256种以内，png8</li>
<li>先优化单独的图像，再优化Sprite</li>
<li>控制大小和对齐减少饭局吃像素的数量。</li>
<li>避免使用对角线渐变，无法被平铺</li>
<li>避免在IE6种使用alpha透明图像</li>
<li>每2－3个像素改变渐变的颜色，而不是每个像素都改变</li>
<li>处理logo的时候要小心，logo很易识别，就算非常小的修改也会很容易被注意到。</li>
</ul>

<h1 id="其他图像优化方法">其他图像优化方法</h1>

<h2 id="避免对图像进行缩放">避免对图像进行缩放</h2>

<p>使用合适的尺寸,这样可以明显的节省流量。</p>

<h2 id="favicons">favicons</h2>

<ul>
<li>建立favicon，不管怎样，浏览器都会请求，避免不必要的404错误。</li>
<li>添加Expires头，添加缓存。</li>
<li>可以通过link标签制定路径，使用CDN缓存。</li>
<li>保持较小的图标大小，通常文件大小保持在1kb左右。</li>
<li>使用优化工具进一步优化。</li>
</ul>

<h2 id="apple触摸图标">Apple触摸图标</h2>

<p><code>&lt;link rel=&quot;apple-touch-icon&quot; href=&quot;http://CDN/name.png&quot;&gt;</code></p>

<p>iphone客户端只会在用户将页面添加到桌面的时候才会请求这个文件。</p>

<h1 id="资料">资料</h1>

<p><strong>高性能网站建设进阶指南</strong>
<a href="https://isux.tencent.com/introduction-of-webp.html">WebP 探寻之路</a></p>

<p><a href="http://www.uisdc.com/picture-optimization-techniques-2">设计中优化图片的6大技巧</a></p>

<p><a href="http://www.uisdc.com/picture-design-experience">图片格式与设计那点事儿</a></p>

  </div>
</div>
<div class="container has-text-centered">
    
</div>

<div class="container has-text-centered">
  
</div>
<section class="section">
  <div class="container has-text-centered">
    <p></p>
  </div>
</section>


